//Initialize utils
App.Utils = App.Utils || {
	
	// Hash of preloaded properties for the app
    properties:{'serverURL':'http://localhost/ApplicationServer/rest/api/',
    			'property2':'value2',
    			'property3':'value3'},
    			
    // Hash of preloaded views for the app
    views:{},
    
    // Messages for the app
    messages:{},

    // Get Property by Name from hash of preloaded properties
    getProperty:function (name) {
        return this.properties[name];
    },
    
    // Get View by Name from hash of preloaded views
    setSuccessMessage:function (message) {
    	this.messages = {type : 'OK',
    					 message : message};
    },
    
    setFailureMessage:function (message) {    	
    	this.messages = {type : 'Error',
				 		 message : message};
    },
    
    // Get View by Name from hash of preloaded views
    getView:function (name) {    	
        return this.views[name];
    },

    // Recursively pre-load all the views for the app.
    loadViews:function (names, callback) {
        var that = this;
        var loadView = function (index) {
            var name = names[index];     
            $.ajax({
            	  url: 'src/' + name + '.html',
            	  success: function (data) {
                      that.views[name] = data;
                      index++;
                      if (index < names.length) {
                    	  loadView(index);
                      } else {
                          callback();
                      }
                  },
            	  cache :false
            	});
        };
        loadView(0);
    },    
    
    //Uses the change page method of JQueryMobile
    changePage:function (page) {
    	$(page.el).attr('data-role', 'page');
    	$('body').append($(page.el));
    	// JQuery Mobile Change Page
        var transition = $.mobile.defaultPageTransition;    	
    	$.mobile.changePage($(page.el), {changeHash:false, transition: transition});
    	//Call the validation
    	App.Utils.displayApplicationMessages();
    },
    
    //Puts the loading widget on the screen
    mask:function (){
    	$.mobile.loading('show', {
			theme: 'no'
        });
    },
    
    //Removes the loading widget on the screen
    unmask:function (){
    	$.mobile.loading('hide');
    },
    
    //Display Application Messages if there is a message to show
    //in the messages hash
    displayApplicationMessages: function (){
    	if (_.size(this.messages) > 0){
    		$.mobile.loading( 'show', {
    			text: this.messages.message,
    			textVisible: true,
    			theme: this.messages.type == 'OK' ? 'e' : 'd',
    			textonly: true
            });
        	setTimeout(function(){$.mobile.loading('hide');},2000);
        	//Resets the messages queue
        	this.messages={};
    	}
    },
    
    //Display Validation errors in a specific form
    displayValidationErrors: function (messages) {
    	//Remove all existing validation errors
    	$('label.error').remove();
    	//Check for actual errors to show
        for (var key in messages) {
            if (messages.hasOwnProperty(key)) {
                this.addValidationError(key, messages[key]);
            }
        }
    },

    //Display Validation error in a specific field
    addValidationError: function (field, message) {
    	//Removes all existing validation errors in the field
    	this.removeValidationError(field);
    	//Select the input with the error
        var input = $('#'+field).closest('div[data-role=\'fieldcontain\']');
        //Add a label error with the desired message
        var html = '<label for=\"'+field+'\" class=\"error\">'+message+'</label>';
        input.append(html);
    },

    //Remove Validation error in a specific field
    removeValidationError: function (field) {
    	//Remove the label error in the selected input
    	var input = $('#'+field).closest('div[data-role=\'fieldcontain\']');
    	$('label.error', input).remove();
    },
    
    //Custom Validate single item in a given model
    validateItem: function (model, key) {
        return (model.validators[key]) ? model.validators[key](model.get(key)) : {isValid: true};
    },
    
    //Custom Validate all elements of the given model
    validateAll: function (model) {
        var messages = {};        
        for (var key in model.validators) {
            if(model.validators.hasOwnProperty(key)) {
                var check = model.validators[key](model.get(key));
                if (check.isValid === false) {
                    messages[key] = check.message;
                }
            }
        }
        return _.size(messages) > 0 ? {isValid: false, messages: messages} : {isValid: true};
    },
    
    //Render a date, specifically the related days with the selected year and month.    
    renderDate:function(fieldName, initialYear, finalYear, initialDate) {
    	var year = $('#'+fieldName+'-year').val();
    	var month = $('#'+fieldName+'-month').val();
    	var day = $('#'+fieldName+'-day').val();
    	
    	var days = 0;
		if (year == '' || month == '')
			days = 31;
		else{
			if (day != ''){
				//Initializes the date object, 
				//with day the month should be provided since 0 to 11
				var date = new Date(year, month-1, day);
				//Set the selected values for a valid date
				year = date.getFullYear();
				month = date.getMonth() + 1;
				day = date.getDate();
			}
			//Obtains the number of days by a given year and month
			//the month should be provided since 1 to 12
			date = new Date(year, month, 0);
    		days = date.getDate();
		}
			
		var dayOptions = $('#'+fieldName+'-day').prop('options');
		dayOptions.length = 0;
		dayOptions[dayOptions.length] = new Option('DD','');
		//The day options are generated every time something changes
		for (var i = 1; i <= days; i++)
			dayOptions[dayOptions.length] = new Option(i,i);
		
		var yearOptions = $('#'+fieldName+'-year').prop('options');
		yearOptions.length = 0;
		yearOptions[yearOptions.length] = new Option('YY','');
		//The year options are generated every time something changes
		//The expected values are between the initial and final year 
		for (var i = initialYear; i <= finalYear; i++)
			yearOptions[yearOptions.length] = new Option(i,i);
		
		//If the initial date is set, it will be selected on the select menus
    	if (initialDate != null){
    		$('#'+fieldName+'-year').val(initialDate.getFullYear());
    		$('#'+fieldName+'-month').val(initialDate.getMonth() + 1);
    		$('#'+fieldName+'-day').val(initialDate.getDate());
    	}
    	//If not the previous selected value is set again if it exists in the predefines values
    	else{
    		//Search for the value in the options of the select
    		var yearExists = 0 != $('#'+fieldName+'-year option[value='+year+']').length;
    		var dayExists = 0 != $('#'+fieldName+'-day option[value='+day+']').length;
    		//Set the previous values
    		$('#'+fieldName+'-year').val((yearExists)?year:'');
    		$('#'+fieldName+'-month').val(month);
    		$('#'+fieldName+'-day').val((dayExists)?day:'');
    	}
    	//Refresh the select menus to show the selected values
    	$('#'+fieldName+'-year').selectmenu('refresh');
		$('#'+fieldName+'-month').selectmenu('refresh');
		$('#'+fieldName+'-day').selectmenu('refresh');
    },
    //Used to initialize the date related values year, month, day and format in a given model
    //Every time the date changes they are refreshed
    changeDate:function(model,dateField){
    	var date = model.get(dateField);
    	if (date != null){
			date = new Date(date);
			//Way to set an attribute key from a string
			attrs = {};
			key = dateField + '-format';
			attrs[key] = date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate();
			key = dateField + '-year';
			attrs[key] = date.getFullYear();
			key = dateField + '-month';
			attrs[key] = date.getMonth() + 1;
			key = dateField + '-day';
			attrs[key] = date.getDate();
			//The four related values are set
			model.set(attrs,{"silent":true});
    	}	
    },
    //Set a valid date if the model is complete with the three attributes year month and day
    //If the three attributes are not set the 
    //date should be null because it means the date is being edited
    setDate: function(model,dateField){
    	//Obtains the three attributes
    	var year = model.get(dateField + '-year');
    	var month = model.get(dateField + '-month');
    	var day = model.get(dateField + '-day');
    	var value = null;
    	//If the date attributes are set.
    	//If not the date should be null
    	if (year != null && year != '' 
    			&& month != null && month != ''
    			&& day != null && day != ''){
    		var sdate = new Date(year, parseInt(month) - 1, day);
    		value = sdate;
    	}
    	//Way to set an attribute key from a string
		var key = dateField;
		attrs = {};
		attrs[key] = value;
		model.set(attrs);
    }
};
